Swift Playground 教程

1. Swift 简介和特性

Swift 是一种由 Apple 开发的多范式编程语言,旨在为 iOS、macOS、watchOS 和 tvOS 提供安全、快速和现代的编程体验。Swift 结合了 C 和 Objective-C 的优点,同时摒弃了它们的许多复杂性。

主要特性:

  • 安全性:Swift 通过类型推断和可选类型(Optionals)减少了空指针异常的风险。
  • 速度:Swift 的编译器优化使其在性能上接近 C++。
  • 现代性:Swift 支持函数式编程、面向对象编程和协议导向编程。

2. Xcode 安装和使用

Xcode 是 Apple 的集成开发环境(IDE),用于开发 macOS 和 iOS 应用程序。它包含了 Swift 编译器、调试工具和界面构建器。

安装步骤:

  1. 打开 Mac App Store。
  2. 搜索 "Xcode" 并点击 "获取"。
  3. 安装完成后,打开 Xcode。

使用 Xcode:

  • 创建新项目:选择 "Create a new Xcode project",然后选择 "App" 模板。
  • 界面构建器:使用 Interface Builder 设计用户界面。
  • 编写代码:在 ViewController.swift 文件中编写 Swift 代码。

3. Swift Playground

Swift Playground 是 Xcode 中的一个交互式环境,允许你实时编写和运行 Swift 代码。它非常适合学习和实验 Swift 语言。

创建 Playground:

  1. 打开 Xcode。
  2. 选择 "Get started with a playground"。
  3. 选择 "Blank" 模板并命名你的 Playground。

使用 Playground:

  • 实时反馈:代码的执行结果会立即显示在右侧的 "Results" 面板中。
  • 文档注释:使用 /// 编写文档注释,Playground 会自动生成文档视图。
/// 这是一个简单的 Swift Playground 示例
var greeting = "Hello, Playground!"
print(greeting)

4. 基本语法和数据类型

Swift 的基本语法简洁明了,数据类型丰富多样。

数据类型:

  • 整数:Int
  • 浮点数:Double, Float
  • 布尔值:Bool
  • 字符串:String
  • 可选类型:Optional<T> 或 T?
let integerValue: Int = 42
let doubleValue: Double = 3.14
let booleanValue: Bool = true
let stringValue: String = "Hello, Swift!"
let optionalValue: Int? = nil

5. 变量和常量

在 Swift 中,变量和常量分别使用 var 和 let 关键字声明。

变量:

var variableName = "This is a variable"
variableName = "You can change me"

常量:

let constantName = "This is a constant"
// constantName = "You cannot change me"  // 这行代码会导致编译错误

6. 运算符和表达式

Swift 支持多种运算符,包括算术运算符、比较运算符和逻辑运算符。

算术运算符:

let sum = 5 + 3
let difference = 10 - 4
let product = 2 * 3
let quotient = 8 / 2

比较运算符:

let isEqual = (5 == 5)  // true
let isGreater = (7 > 3)  // true

逻辑运算符:

let andResult = (true && false)  // false
let orResult = (true || false)   // true

7. 条件语句 (if, switch)

条件语句用于根据条件执行不同的代码块。

if 语句:

let temperature = 25
if temperature > 30 {
    print("It's hot!")
} else if temperature > 20 {
    print("It's warm.")
} else {
    print("It's cold.")
}

switch 语句:

let day = "Monday"
switch day {
case "Monday":
    print("Start of the week")
case "Friday":
    print("End of the week")
default:
    print("Midweek")
}

8. 循环 (for-in, while, repeat-while)

循环用于重复执行代码块。

for-in 循环:

for i in 1...5 {
    print(i)
}

while 循环:

var count = 0
while count < 5 {
    print(count)
    count += 1
}

repeat-while 循环:

var counter = 0
repeat {
    print(counter)
    counter += 1
} while counter < 5

9. 控制转移语句 (break, continue)

控制转移语句用于改变循环的执行流程。

break 语句:

for i in 1...10 {
    if i == 5 {
        break
    }
    print(i)
}

continue 语句:

for i in 1...10 {
    if i % 2 == 0 {
        continue
    }
    print(i)
}

10. 数组

数组是一种有序的集合,可以存储多个相同类型的元素。

创建数组:

var numbers = [1, 2, 3, 4, 5]

访问元素:

let firstNumber = numbers[0]  // 1

添加元素:

numbers.append(6)

删除元素:

numbers.remove(at: 2)

11. 集合

集合是一种无序的集合,存储唯一的元素。

创建集合:

var uniqueNumbers: Set<Int> = [1, 2, 3, 4, 5]

添加元素:

uniqueNumbers.insert(6)

删除元素:

uniqueNumbers.remove(3)

12. 字典

字典是一种键值对的集合,键必须是唯一的。

创建字典:

var scores = ["Alice": 90, "Bob": 85, "Charlie": 88]

访问值:

let aliceScore = scores["Alice"]  // 90

添加或更新值:

scores["David"] = 92

删除值:

scores["Bob"] = nil

13. 函数定义和调用

函数是执行特定任务的代码块。

定义函数:

func greet(name: String) -> String {
    return "Hello, \(name)!"
}

调用函数:

let greetingMessage = greet(name: "Alice")
print(greetingMessage)

14. 参数和返回值

函数可以有多个参数和返回值。

多参数函数:

func add(a: Int, b: Int) -> Int {
    return a + b
}

无返回值函数:

func printSum(a: Int, b: Int) {
    print(a + b)
}

15. 闭包表达式

闭包是自包含的代码块,可以在代码中传递和使用。

闭包表达式:

let addClosure = { (a: Int, b: Int) -> Int in
    return a + b
}

调用闭包:

let result = addClosure(3, 5)  // 8

16. 尾随闭包

尾随闭包是一种简化闭包调用的语法。

尾随闭包:

func performOperation(a: Int, b: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(a, b)
}

let result = performOperation(a: 3, b: 5) { (a, b) in
    return a * b
}

17. 枚举定义和使用

枚举是一种自定义类型,用于定义一组相关的值。

定义枚举:

enum Direction {
    case north
    case south
    case east
    case west
}

使用枚举:

let currentDirection = Direction.north

18. 关联值和原始值

枚举可以有关联值和原始值。

关联值:

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

let productBarcode = Barcode.upc(8, 85909, 51226, 3)

原始值:

enum Planet: Int {
    case mercury = 1
    case venus
    case earth
}

let earthNumber = Planet.earth.rawValue  // 3

19. 结构体定义和使用

结构体是一种值类型,用于封装一组相关的属性和方法。

定义结构体:

struct Point {
    var x: Int
    var y: Int
}

使用结构体:

let origin = Point(x: 0, y: 0)

20. 值类型 vs 引用类型

值类型在赋值时会创建副本,而引用类型则共享同一个实例。

值类型:

var point1 = Point(x: 0, y: 0)
var point2 = point1
point2.x = 10
print(point1.x)  // 0

引用类型:

class Circle {
    var radius: Double
    init(radius: Double) {
        self.radius = radius
    }
}

var circle1 = Circle(radius: 5.0)
var circle2 = circle1
circle2.radius = 10.0
print(circle1.radius)  // 10.0

21. 类定义和实例化

类是一种引用类型,用于封装一组相关的属性和方法。

定义类:

class Person {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    func greet() {
        print("Hello, my name is \(name) and I am \(age) years old.")
    }
}

实例化类:

let alice = Person(name: "Alice", age: 30)
alice.greet()

22. 属性和方法

属性用于存储类的状态,方法用于定义类的行为。

属性:

class Rectangle {
    var width: Double
    var height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

方法:

class Rectangle {
    var width: Double
    var height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }

    func area() -> Double {
        return width * height
    }
}

23. 继承和多态

继承允许一个类继承另一个类的属性和方法,多态允许子类重写父类的方法。

继承:

class Vehicle {
    var speed: Double

    init(speed: Double) {
        self.speed = speed
    }

    func describe() {
        print("This vehicle is moving at \(speed) km/h.")
    }
}

class Car: Vehicle {
    var numberOfDoors: Int

    init(speed: Double, numberOfDoors: Int) {
        self.numberOfDoors = numberOfDoors
        super.init(speed: speed)
    }
}

多态:

class Bicycle: Vehicle {
    override func describe() {
        print("This bicycle is moving at \(speed) km/h.")
    }
}

let vehicles: [Vehicle] = [Car(speed: 100, numberOfDoors: 4), Bicycle(speed: 20)]
for vehicle in vehicles {
    vehicle.describe()
}

24. 初始化和反初始化

初始化器用于设置类的初始状态,反初始化器用于在对象销毁前执行清理操作。

初始化器:

class Person {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

反初始化器:

class FileHandler {
    var fileDescriptor: Int

    init(fileDescriptor: Int) {
        self.fileDescriptor = fileDescriptor
    }

    deinit {
        close(fileDescriptor)
    }
}

25. 协议定义和遵循

协议定义了一组方法和属性的蓝图,类、结构体和枚举可以遵循协议。

定义协议:

protocol Greetable {
    var name: String { get }
    func greet()
}

遵循协议:

class Person: Greetable {
    var name: String

    init(name: String) {
        self.name = name
    }

    func greet() {
        print("Hello, my name is \(name).")
    }
}

26. 协议扩展

协议扩展允许为协议添加默认实现。

协议扩展:

extension Greetable {
    func greet() {
        print("Hello, my name is \(name).")
    }
}

27. 类型扩展

类型扩展允许为现有类型添加新功能。

类型扩展:

extension Int {
    func squared() -> Int {
        return self * self
    }
}

let number = 5
print(number.squared())  // 25

28. 错误协议

错误协议用于定义自定义错误类型。

定义错误:

enum NetworkError: Error {
    case invalidURL
    case timeout
}

抛出错误:

func fetchData(from url: String) throws -> Data {
    guard let url = URL(string: url) else {
        throw NetworkError.invalidURL
    }
    // 模拟网络请求
    return Data()
}

29. throws 和 try 语句

throws 关键字用于标记可能抛出错误的函数,try 关键字用于调用这些函数。

使用 throws 和 try:

do {
    let data = try fetchData(from: "https://example.com")
    print("Data fetched successfully.")
} catch NetworkError.invalidURL {
    print("Invalid URL.")
} catch {
    print("An error occurred: \(error).")
}

30. 错误传递

错误可以通过函数调用链传递。

错误传递:

func processData(from url: String) throws -> Data {
    let data = try fetchData(from: url)
    // 处理数据
    return data
}

31. 泛型函数

泛型函数允许函数处理不同类型的参数。

泛型函数:

func swapValues<T>(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
}

var x = 5
var y = 10
swapValues(&x, &y)
print("x: \(x), y: \(y)")  // x: 10, y: 5